home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 5 / MacMania 5.toast / / Internet software / NewsWatcher / NW Source / Source / send.c < prev    next >
Text File  |  1997-01-09  |  20KB  |  798 lines

  1. /*----------------------------------------------------------------------------
  2.  
  3.     send.c
  4.  
  5.     This module handles sending postings and mail messages.
  6.     
  7.     Copyright © 1994-1997, Northwestern University.
  8.  
  9. ----------------------------------------------------------------------------*/
  10.  
  11. #include <string.h>
  12.  
  13. #include "glob.h"
  14. #include "dialog.h"
  15. #include "news.h"
  16. #include "send.h"
  17. #include "smtp.h"
  18. #include "header.h"
  19. #include "newswatcher.h"
  20. #include "status.h"
  21. #include "message.h"
  22. #include "charset.h"
  23. #include "cancel.h"
  24. #include "memutil.h"
  25. #include "strutil.h"
  26. #include "ic.h"
  27.  
  28.  
  29.  
  30. #define kPostAlert            135            /* Post confirm dialog */
  31. #define kPostCancelAlert    147            /* Post cancel dialog */
  32.  
  33.  
  34.  
  35. /*----------------------------------------------------------------------------
  36.     Wrap 
  37.     
  38.     Wraps paragraphs to lines of at most 74 characters long.
  39.             
  40.     Entry:    text = handle to text to be wrapped.
  41.             start = offset in text of beginning of text to be wrapped.
  42.             end = offset in text of end of text to be wrapped.
  43.  
  44.      Only lines which which exceed 80 characters in length are wrapped.
  45. ----------------------------------------------------------------------------*/
  46.  
  47. void Wrap (Handle text, long start, long end)
  48. {
  49.     char *p, *pEnd, *q, *lastSpace;
  50.     
  51.     p = *text + start;
  52.     pEnd = *text + end;
  53.     while (p < pEnd) {
  54.         q = p;
  55.         while (q < pEnd && *q != CR) q++;
  56.         if (q - p > 80) {
  57.             q = p;
  58.             lastSpace = 0;
  59.             while (true) {
  60.                 while (q < pEnd && *q != ' ' && *q != CR) q++;
  61.                 if (q < pEnd && *q == ' ') {
  62.                     while (q < pEnd && *q == ' ') q++;
  63.                     q--;
  64.                 }
  65.                 if (q - p >= 75 && lastSpace != 0) {
  66.                     *lastSpace = CR;
  67.                     p = lastSpace + 1;
  68.                     lastSpace = 0;
  69.                 }
  70.                 if (q >= pEnd || *q == CR) break;
  71.                 lastSpace = q;
  72.                 q++;
  73.             }
  74.         }
  75.         p = q+1;
  76.     }
  77. }
  78.  
  79.  
  80.  
  81. /*----------------------------------------------------------------------------
  82.     UnWrap 
  83.     
  84.     Unwraps paragraphs.
  85.             
  86.     Entry:    text = handle to text to be unwrapped.
  87.             start = offset in text of beginning of text to be unwrapped.
  88.             end = offset in text of end of text to be unwrapped.
  89. ----------------------------------------------------------------------------*/
  90.  
  91. void UnWrap (Handle text, long start, long end)
  92. {
  93.     char *p, *pEnd;
  94.     
  95.     p = *text + start;
  96.     pEnd = *text + end;
  97.     while (p < pEnd) {
  98.         while (p < pEnd && *p != CR) p++;
  99.         p++;
  100.         if (p < pEnd) {
  101.             if (*p == ' ' || *p == '\t') continue;
  102.             if (*p == CR) {
  103.                 while (p < pEnd && *p == CR) p++;
  104.                 continue;
  105.             }
  106.             *(p-1) = ' ';
  107.         }
  108.     }
  109. }
  110.  
  111.  
  112.  
  113. /*----------------------------------------------------------------------------
  114.     GetRecipients 
  115.     
  116.     Gets recipient addresses for an email message.
  117.             
  118.     Entry:    text = message to be mailed, including headers.
  119.             hdr = C-format message header to process (To, Cc, or Bcc).
  120.             
  121.     Exit:    function result = error code.
  122.             *recipients = handle to comma-separated list of
  123.                 recipient email addresses, or nil if header not found.
  124. ----------------------------------------------------------------------------*/
  125.  
  126. static OSErr GetRecipients (Handle text, char *hdr, Handle *recipients)
  127. {
  128.     Handle recip;
  129.     OSErr err = noErr;
  130.     char *p, *pEnd, *q, *r, *begin, *end;
  131.     long len;
  132.     short parenLevel;
  133.     Boolean insideQuotedString = false;
  134.     
  135.     err = FindHeaderHandle(text, hdr, &recip);
  136.     if (err != noErr) return err;
  137.     if (recip == nil) {
  138.         *recipients = nil;
  139.         return noErr;
  140.     }
  141.     
  142.     /* Strip comments in parentheses and blanks. */
  143.     
  144.     p = q = *recip;
  145.     len = MyGetHandleSize(recip);
  146.     pEnd = p + len;
  147.     while (p < pEnd) {
  148.         if (*p == '(') {
  149.             parenLevel = 1;
  150.             p++;
  151.             while (p < pEnd && parenLevel > 0) {
  152.                 if (*p == '(') {
  153.                     parenLevel++;
  154.                 } else if (*p == ')') {
  155.                     parenLevel--;
  156.                 }
  157.                 p++;
  158.             }
  159.         } else if (*p == ' ') {
  160.             p++;
  161.         } else {
  162.             *q++ = *p++;
  163.         }
  164.     }
  165.     len = q - *recip;
  166.     
  167.     /* Extract recipients */
  168.     
  169.     p = q = *recip;
  170.     pEnd = p + len;
  171.     while (p < pEnd) {
  172.         r = p;
  173.         while (r < pEnd) {
  174.             if (*r == '"') {
  175.                 insideQuotedString = true;
  176.                 r++;
  177.                 while (r < pEnd && *r != '"') r++;
  178.                 if (r >= pEnd) break;
  179.                 insideQuotedString = false;
  180.                 r++;
  181.             } else if (*r == '<' || *r == ',') {
  182.                 break;
  183.             } else {
  184.                 r++;
  185.             }
  186.         }
  187.         if (insideQuotedString) break;
  188.         if (r >= pEnd || *r == ',') {
  189.             begin = p;
  190.             end = r-1;
  191.         } else {
  192.             r++;
  193.             begin = r;
  194.             while (r < pEnd && *r != '>') r++;
  195.             end = r-1;
  196.         } 
  197.         p = r;
  198.         while (p < pEnd && *p != ',') p++;
  199.         if (*p == ',') p++;
  200.         len = end - begin + 1;
  201.         if (q != *recip) *q++ = ',';
  202.         BlockMoveData(begin, q, len);
  203.         q += len;
  204.     }
  205.     len = q - *recip;
  206.     MySetHandleSize(recip, len);
  207.     *recipients = recip;
  208.     return noErr;
  209. }
  210.  
  211.  
  212.  
  213. /*----------------------------------------------------------------------------
  214.     SendMailMessage 
  215.     
  216.     Send a mail message.
  217.             
  218.     Entry:    text = message to be mailed, including headers.
  219.             
  220.     Exit:    function result = error code.
  221. ----------------------------------------------------------------------------*/
  222.  
  223. static OSErr SendMailMessage (Handle text)
  224. {
  225.     SmtpStreamRef s;
  226.     OSErr err = noErr;
  227.     Handle to = nil;
  228.     Handle cc = nil;
  229.     Handle bcc = nil;
  230.     long toLen, ccLen, bccLen, len;
  231.     char *q;
  232.     NetServerErrInfo serverErrInfo;
  233.     
  234.     MyICReadSharedPrefs(kICEmail);
  235.     MyICReadSharedPrefs(kICSMTPHost);
  236.     
  237.     err = GetRecipients(text, "To", &to);
  238.     if (err != noErr) goto exit1;
  239.     err = GetRecipients(text, "Cc", &cc);
  240.     if (err != noErr) goto exit1;
  241.     err = GetRecipients(text, "Bcc", &bcc);
  242.     if (err != noErr) goto exit1;
  243.     DeleteHeaderLine(text, "Bcc");        /* Don't actually send "Bcc" header line! */
  244.     
  245.     toLen = to == nil ? 0 : MyGetHandleSize(to);
  246.     ccLen = cc == nil ? 0 : MyGetHandleSize(cc);
  247.     bccLen = bcc == nil ? 0 : MyGetHandleSize(bcc);
  248.     
  249.     len = toLen;
  250.     if (cc != nil) {
  251.         if (len > 0) len++;
  252.         len += ccLen;
  253.     }
  254.     if (bcc != nil) {
  255.         if (len > 0) len++;
  256.         len += bccLen;
  257.     }
  258.     len++;
  259.     
  260.     if (to == nil) {
  261.         err = MyNewHandle(len, &to);
  262.     } else {
  263.         err = MySetHandleSize(to, len);
  264.     }
  265.     if (err != noErr) goto exit1;
  266.     
  267.     q = *to + toLen;
  268.     if (cc != nil) {
  269.         if (q > *to) *q++ = ',';
  270.         BlockMoveData(*cc, q, ccLen);
  271.         q += ccLen;
  272.     }
  273.     if (bcc != nil) {
  274.         if (q > *to) *q++ = ',';
  275.         BlockMoveData(*bcc, q, bccLen);
  276.         q += bccLen;
  277.     }
  278.     *q = 0;
  279.     
  280.     p2cstr(gPrefs.mailServerName);
  281.     err = SmtpOpen((char*)gPrefs.mailServerName, &s);
  282.     c2pstr((char*)gPrefs.mailServerName);
  283.     if (err != noErr) goto exit2;
  284.     
  285.     MyHLock(to);
  286.     err = SmtpSendMessage(s, gPrefs.emailAddress, *to, text);
  287.     MyHUnlock(to);
  288.     if (err != noErr) goto exit2;
  289.     
  290.     err = SmtpClose(s);
  291.     if (err != noErr) goto exit2;
  292.     
  293.     MyDisposeHandle(to);
  294.     MyDisposeHandle(cc);
  295.     MyDisposeHandle(bcc);
  296.     
  297.     return noErr;
  298.     
  299. exit1:
  300.     
  301.     MyDisposeHandle(to);
  302.     MyDisposeHandle(cc);
  303.     MyDisposeHandle(bcc);
  304.     return err;
  305.     
  306. exit2:
  307.     
  308.     MyDisposeHandle(to);
  309.     MyDisposeHandle(cc);
  310.     MyDisposeHandle(bcc);
  311.     if (err == smtpServerErr) {
  312.         SmtpGetServerErrInfo(s, &serverErrInfo);
  313.         SmtpClose(s);
  314.         ServerErrorMessage(kStrMail, serverErrInfo.command, serverErrInfo.response);
  315.         return userCanceledErr;
  316.     } else {
  317.         p2cstr(gPrefs.mailServerName);
  318.         SaveNetErrorInfo(kStrMail, (char*)gPrefs.mailServerName);
  319.         c2pstr((char*)gPrefs.mailServerName);
  320.         return err;
  321.     }
  322. }
  323.  
  324.  
  325.  
  326. /*----------------------------------------------------------------------------
  327.     AreYouSure 
  328.     
  329.     Present "Are you sure you want to post" alert.
  330.             
  331.     Exit:    function result = error code.
  332. ----------------------------------------------------------------------------*/
  333.  
  334. static OSErr AreYouSure (void)
  335. {
  336.     DialogPtr dlg = nil;
  337.     short item;
  338.     OSErr err = noErr;
  339.  
  340.     if (!gPrefs.areYouSureAlert) return noErr;
  341.     err = MyGetNewDialog(kPostAlert, ok, cancel, &dlg);
  342.     if (err != noErr) return err;
  343.     SysBeep(0);
  344.     MyModalDialog(dlg, gDialogFilterUPP, &item);
  345.     err = DoClose(dlg);
  346.     if (err != noErr) return err;
  347.     return item == ok ? noErr : userCanceledErr;
  348. }
  349.  
  350.  
  351.  
  352. /*----------------------------------------------------------------------------
  353.     BuildMessageForPrinting 
  354.     
  355.     Build a message for printing.
  356.             
  357.     Entry:    wind = pointer to message window.
  358.             
  359.     Exit:    function result = error code.
  360.             *messageText = handle to message text to be printed.
  361. ----------------------------------------------------------------------------*/
  362.  
  363. OSErr BuildMessageForPrinting (WindowPtr wind, Handle *messageText)
  364. {
  365.     TWindow **info;
  366.     TEHandle theTE;
  367.     Handle text = nil;
  368.     Handle msg = nil;
  369.     Handle newsgroups, to, subject, cc, bcc, replyto;
  370.     Handle followupto, keywords, distribution;
  371.     Handle extraMail, signature, references;
  372.     OSErr err = noErr, err1 = noErr;
  373.     long sigLen, textLen, newTextLen;
  374.     char *q;
  375.     Boolean newsIcon, mailIcon, selfIcon;
  376.  
  377.     info = (TWindow**)GetWRefCon(wind);
  378.     theTE = (**info).theTE;
  379.     text = (**theTE).hText;
  380.     newsgroups = (**(**info).newsgroupsField).hText;
  381.     to = (**(**info).toField).hText;
  382.     subject = (**(**info).subjectField).hText;
  383.     cc = (**(**info).ccField).hText;
  384.     bcc = (**(**info).bccField).hText;
  385.     replyto = (**(**info).replytoField).hText;
  386.     followupto = (**(**info).followuptoField).hText;
  387.     keywords = (**(**info).keywordsField).hText;
  388.     distribution = (**(**info).distributionField).hText;
  389.     extraMail = (**(**info).extraMailField).hText;
  390.     signature = (**(**info).signatureField).hText;
  391.     references = (**info).references;
  392.     newsIcon = (**info).newsIcon;
  393.     mailIcon = (**info).mailIcon;
  394.     selfIcon = (**info).selfIcon;
  395.     
  396.     err = MyHandToHand(&text);
  397.     if (err != noErr) return err;
  398.     
  399.     textLen = MyGetHandleSize(text);
  400.     q = *text + textLen - 1;
  401.     while (q > *text && isLWSPorCR(*q)) q--;
  402.     q++;
  403.     newTextLen = q - *text;
  404.     if (newTextLen != textLen) {
  405.         textLen = newTextLen;
  406.         MySetHandleSize(text, textLen);
  407.     }
  408.  
  409.     sigLen = MyGetHandleSize(signature);
  410.     if (sigLen > 0) {
  411.         newTextLen = textLen + sigLen + 1;
  412.         err = MySetHandleSize(text, newTextLen);
  413.         if (err != noErr) goto exit;
  414.         q = *text + textLen;
  415.         *q++ = CR;
  416.         BlockMoveData(*signature, q, sigLen);
  417.         textLen = newTextLen;
  418.     }
  419.     
  420.     if (textLen == 0) {
  421.         textLen = 1;
  422.         err = MySetHandleSize(text, textLen);
  423.         if (err != noErr) goto exit;
  424.         **text = ' ';
  425.     }
  426.     
  427.     if (!mailIcon) to = cc = bcc = nil;
  428.     if (!newsIcon) newsgroups = followupto = distribution = nil;
  429.     err = MakeMailHeader(subject, to, cc, bcc, (**info).from,
  430.         (**info).selfIcon, replyto, keywords, extraMail,
  431.         newsgroups, followupto, distribution,
  432.         references, &msg);
  433.     if (err != noErr) goto exit;
  434.     err = MyHandAndHand(text, msg);
  435.     if (err != noErr) goto exit;
  436.     
  437.     *messageText = msg;
  438.     MyDisposeHandle(text);
  439.     return noErr;
  440.     
  441. exit:
  442.  
  443.     MyDisposeHandle(text);
  444.     MyDisposeHandle(msg);
  445.     return err;
  446. }
  447.  
  448.  
  449.  
  450. /*----------------------------------------------------------------------------
  451.     MessageBodyContainsOnlyQuotedText 
  452.     
  453.     Check to see if a message body contains only quoted text.
  454.             
  455.     Entry:    text = handle to message body text.
  456.             quoteString = handle to quote string.
  457.             
  458.     Exit:    function result = true if message body contains only quoted text
  459.                 and blank lines (not counting the beginning attribution line).
  460. ----------------------------------------------------------------------------*/
  461.  
  462. static Boolean MessageBodyContainsOnlyQuotedText (Handle text, Handle quoteString)
  463. {
  464.     long textLen, quoteStringLen;
  465.     char *p, *pEnd, *r;
  466.     CStr255 attributionStr1, attributionStr3;
  467.     short attributionStr1Len, attributionStr3Len;
  468.     
  469.     textLen = MyGetHandleSize(text);
  470.     quoteStringLen = MyGetHandleSize(quoteString);
  471.     if (quoteStringLen == 0) return false;
  472.     
  473.     GetCString(kStrQuoteStr1, attributionStr1);
  474.     GetCString(kStrQuoteStr3, attributionStr3);
  475.     attributionStr1Len = strlen(attributionStr1);
  476.     attributionStr3Len = strlen(attributionStr3);
  477.  
  478.     p = *text;
  479.     pEnd = p + textLen;
  480.     
  481.     /* Check the first line of the message body. If it is the attribution line
  482.        "In article <...>, so-and-so wrote:", then skip over it. */
  483.     
  484.     r = p;
  485.     while (r < pEnd && *r != CR) r++;
  486.     if (r - p > attributionStr1Len + attributionStr3Len + 10) {
  487.         if (MyStrNEqual(p, attributionStr1, attributionStr1Len) &&
  488.             *(p + attributionStr1Len) == '<' &&
  489.             MyStrNEqual(r - attributionStr3Len, attributionStr3, attributionStr3Len))
  490.         {
  491.             p = r+1;
  492.         }
  493.     }
  494.     
  495.     /* Check the remaining lines of the message body for only quoted and blank
  496.        lines. */
  497.     
  498.     while (p < pEnd) {
  499.         r = p;
  500.         while (r < pEnd && isLWSP(*r)) r++;
  501.         if (r >= pEnd) return true;
  502.         if (*r == CR) {        /* all blank line */
  503.             p = r+1;
  504.             continue;
  505.         }
  506.         if (p + quoteStringLen > pEnd) return false;
  507.         if (!MyStrNEqual(p, *quoteString, quoteStringLen)) return false;
  508.         p = r+1;
  509.         while (p < pEnd && *p != CR) p++;
  510.         p++;
  511.     }
  512.     
  513.     return true;
  514. }
  515.             
  516.  
  517.  
  518.  
  519. /*----------------------------------------------------------------------------
  520.     MakeAlsoPostedToText 
  521.     
  522.     Construct the "(A copy of this message was also posted to...)" text for
  523.     a mail message which is also being posted.
  524.             
  525.     Entry:    headers = handle to header text for mail message.
  526.             
  527.     Exit:    function result = error code.
  528.             *alsoPostedTo = handle to extra "also posted to" text to
  529.                 be added to beginning of mail message.
  530. ----------------------------------------------------------------------------*/
  531.  
  532. static OSErr MakeAlsoPostedToText (Handle headers, Handle *alsoPostedTo)
  533. {            
  534.     CStr255 str;
  535.     OSErr err = noErr;
  536.     Handle h = nil;
  537.     Handle newsgroups = nil;
  538.  
  539.     GetCString(kStrCopyAlsoPostedTo, str);
  540.     err = MyPtrToHand(str, &h, strlen(str));
  541.     if (err != noErr) goto exit;
  542.     err = FindHeaderHandle(headers, "Newsgroups", &newsgroups);
  543.     if (err != noErr) goto exit;
  544.     if (newsgroups != nil) {
  545.         Munger(newsgroups, 0, ",", 1, ", ", 2);
  546.         err = MemError();
  547.         if (err != noErr) goto exit;
  548.         err = MyHandAndHand(newsgroups, h);
  549.         if (err != noErr) goto exit;
  550.     }
  551.     err = MyStrAndHand(")\r\r", h);
  552.     if (err != noErr) goto exit;
  553.     Wrap(h, 0, MyGetHandleSize(h));
  554.     MyDisposeHandle(newsgroups);
  555.     *alsoPostedTo = h;
  556.     return noErr;
  557.     
  558. exit:
  559.  
  560.     MyDisposeHandle(h);
  561.     MyDisposeHandle(newsgroups);
  562.     return err;
  563. }
  564.             
  565.  
  566.  
  567.  
  568. /*----------------------------------------------------------------------------
  569.     SendMessage 
  570.     
  571.     Send a message.
  572.             
  573.     Entry:    wind = pointer to message window.
  574.             
  575.     Exit:    function result = error code.
  576. ----------------------------------------------------------------------------*/
  577.  
  578. OSErr SendMessage (WindowPtr wind)
  579. {
  580.     TWindow **info;
  581.     TEHandle theTE;
  582.     Handle text = nil;
  583.     Handle msg = nil;
  584.     Handle newsgroups, to, subject, cc, bcc, replyto;
  585.     Handle followupto, keywords, distribution;
  586.     Handle extraNews, extraMail, signature, references;
  587.     Handle alsoPostedTo = nil;
  588.     OSErr err = noErr, err1 = noErr;
  589.     long sigLen, textLen, newTextLen;
  590.     char *q;
  591.     Boolean newsIcon, mailIcon, selfIcon;
  592.     short item;
  593.     CStr255 idStr;
  594.     CStr255 statusMsg;
  595.     FSSpec fSpec;
  596.     Boolean wasChanged;
  597.     Boolean posted = false, postIndeterminate = false, mailStarted = false;
  598.     DialogPtr dlg = nil;
  599.  
  600.     info = (TWindow**)GetWRefCon(wind);
  601.     theTE = (**info).theTE;
  602.     text = (**theTE).hText;
  603.     newsgroups = (**(**info).newsgroupsField).hText;
  604.     to = (**(**info).toField).hText;
  605.     subject = (**(**info).subjectField).hText;
  606.     cc = (**(**info).ccField).hText;
  607.     bcc = (**(**info).bccField).hText;
  608.     replyto = (**(**info).replytoField).hText;
  609.     followupto = (**(**info).followuptoField).hText;
  610.     keywords = (**(**info).keywordsField).hText;
  611.     distribution = (**(**info).distributionField).hText;
  612.     extraNews = (**(**info).extraNewsField).hText;
  613.     extraMail = (**(**info).extraMailField).hText;
  614.     signature = (**(**info).signatureField).hText;
  615.     references = (**info).references;
  616.     newsIcon = (**info).newsIcon;
  617.     mailIcon = (**info).mailIcon;
  618.     selfIcon = (**info).selfIcon;
  619.     
  620.     if (!newsIcon && !mailIcon && !selfIcon) {
  621.         ErrorMessageNumber(kStrMustCheckAnIcon);
  622.         return userCanceledErr;
  623.     }
  624.     
  625.     if (HeaderLineIsEmpty(subject)) {
  626.         ErrorMessageNumber(kStrMustSupplySubject);
  627.         return userCanceledErr;
  628.     }
  629.     
  630.     if (newsIcon && HeaderLineIsEmpty(newsgroups)) {
  631.         ErrorMessageNumber(kStrMustSupplyNewsgroup);
  632.         return userCanceledErr;
  633.     }
  634.     
  635.     if (mailIcon && !selfIcon && 
  636.         HeaderLineIsEmpty(to) && HeaderLineIsEmpty(cc) && HeaderLineIsEmpty(bcc)) 
  637.     {
  638.         ErrorMessageNumber(kStrMustSupplyRecipient);
  639.         return userCanceledErr;
  640.     }
  641.     
  642.     err = MyHandToHand(&text);
  643.     if (err != noErr) return err;
  644.     
  645.     textLen = MyGetHandleSize(text);
  646.     q = *text + textLen - 1;
  647.     while (q > *text && isLWSPorCR(*q)) q--;
  648.     q++;
  649.     newTextLen = q - *text;
  650.     if (newTextLen != textLen) {
  651.         textLen = newTextLen;
  652.         MySetHandleSize(text, textLen);
  653.     }
  654.     
  655.     if (textLen == 0) {
  656.         ErrorMessageNumber(kStrMustSupplyBody);
  657.         err = userCanceledErr;
  658.         goto exit;
  659.     }
  660.     
  661.     if (newsIcon && (**info).isFollowup && 
  662.         MessageBodyContainsOnlyQuotedText(text, (**(**info).quoteStringField).hText)) 
  663.     {
  664.         ErrorMessageNumber(kStrOnlyQuotedText);
  665.         err = userCanceledErr;
  666.         goto exit;
  667.     }
  668.     
  669.     if (newsIcon) {
  670.         err = AreYouSure();
  671.         if (err != noErr) goto exit;
  672.     }
  673.     
  674.     if ((**info).wrapOnSend) Wrap(text, 0, textLen);
  675.  
  676.     sigLen = MyGetHandleSize(signature);
  677.     if (sigLen > 0) {
  678.         newTextLen = textLen + sigLen + 1;
  679.         err = MySetHandleSize(text, newTextLen);
  680.         if (err != noErr) goto exit;
  681.         q = *text + textLen;
  682.         *q++ = CR;
  683.         BlockMoveData(*signature, q, sigLen);
  684.         textLen = newTextLen;
  685.     }
  686.     
  687.     if (newsIcon) {
  688.         GetCString(kStrPostingMessageStatusMsg, statusMsg);
  689.         err = DisplayStatusMessage(statusMsg);
  690.         if (err != noErr) goto exit;
  691.         err = MakeNewsHeader(newsgroups, subject, replyto, 
  692.             followupto, keywords, distribution, extraNews,
  693.             nil, references, &msg);
  694.         if (err != noErr) goto exit;
  695.         FindHeaderCString(msg, "Message-ID", idStr, sizeof(idStr));
  696.         err = MyHandAndHand(text, msg);
  697.         if (err != noErr) goto exit;
  698.         MapMacToLatin1Handle(msg);
  699.         err = PostArticle(msg, statusMsg, &postIndeterminate);
  700.         posted = err == noErr || postIndeterminate;
  701.         if (err != noErr) goto exit;
  702.         MyDisposeHandle(msg);
  703.         msg = nil;
  704.     }
  705.     
  706.     if (mailIcon || selfIcon) {
  707.         mailStarted = true;
  708.         err = DisplayStatusMessageNumber(kStrMailingMessageStatusMsg);
  709.         if (err != noErr) goto exit;
  710.         if (!mailIcon) to = cc = bcc = nil;
  711.         if (!newsIcon) newsgroups = followupto = distribution = nil;
  712.         err = MakeMailHeader(subject, to, cc, bcc, (**info).from,
  713.             (**info).selfIcon, replyto, keywords, extraMail,
  714.             newsgroups, followupto, distribution,
  715.             references, &msg);
  716.         if (err != noErr) goto exit;
  717.         if (mailIcon && newsIcon) {
  718.             err = MakeAlsoPostedToText(msg, &alsoPostedTo);
  719.             if (err != noErr) goto exit;
  720.             err = MyHandAndHand(alsoPostedTo, msg);
  721.             if (err != noErr) goto exit;
  722.             MyDisposeHandle(alsoPostedTo);
  723.             alsoPostedTo = nil;
  724.         }
  725.         err = MyHandAndHand(text, msg);
  726.         if (err != noErr) goto exit;
  727.         MapMacToLatin1Handle(msg);
  728.         err = SendMailMessage(msg);
  729.         if (err != noErr) goto exit;
  730.     }
  731.  
  732.     (**info).changed = false;
  733.     MyDisposeHandle(text);
  734.     MyDisposeHandle(msg);
  735.     
  736.     if ((**info).alias != nil && gPrefs.savedMsgDelAfterSend) {
  737.         err = ResolveAlias(nil, (**info).alias, &fSpec, &wasChanged);
  738.         if (err == noErr) {
  739.             (**info).alias = nil;
  740.             err = FSpDelete(&fSpec);
  741.             if (err != noErr) return err;
  742.         }
  743.     }
  744.     
  745.     return noErr;
  746.     
  747. exit:
  748.  
  749.     MyDisposeHandle(text);
  750.     MyDisposeHandle(msg);
  751.     MyDisposeHandle(alsoPostedTo);
  752.     if (gCancel && posted) {
  753.         gCancel = false;
  754.         err1 = MyGetNewDialog(kPostCancelAlert, ok, cancel, &dlg);
  755.         if (err1 != noErr) return err1;
  756.         SysBeep(0);
  757.         MyModalDialog(dlg, gDialogFilterUPP, &item);
  758.         err1 = DoClose(dlg);
  759.         if (err1 != noErr) return err1;
  760.         if (item == cancel) {
  761.             GetCString(kStrCancelingStatusMsg, statusMsg);
  762.             err1 = DisplayStatusMessage(statusMsg);
  763.             if (err1 != noErr) return err1;
  764.             err1 = CancelArticle(idStr, newsgroups, statusMsg);
  765.             if (err1 != noErr) return err1;
  766.         } else {
  767.             UncheckNewsIcon(wind);
  768.         }
  769.     } else if (posted && mailStarted) {
  770.         UncheckNewsIcon(wind);
  771.         ReportSystemError(err);
  772.         NoteMessageNumber(kStrPostOKMailErr);
  773.         return userCanceledErr;
  774.     }
  775.     return err;
  776. }
  777.  
  778.  
  779.  
  780. /*----------------------------------------------------------------------------
  781.     SendMessageAndCloseWindow 
  782.     
  783.     Send a message and close the message window.
  784.             
  785.     Entry:    wind = pointer to message window.
  786.     
  787.     Exit:    function result = error code.
  788. ----------------------------------------------------------------------------*/
  789.  
  790. OSErr SendMessageAndCloseWindow (WindowPtr wind)
  791. {
  792.     OSErr err = noErr;
  793.  
  794.     err = SendMessage(wind);
  795.     if (err != noErr) return err;
  796.     return DoClose(wind);
  797. }
  798.